#pragma once
#include "Inet_data.h"

using namespace std;

class Tcp : public nocopy
{
public:
    Tcp(uint16_t port)
        : _port(port)
    {
    }

    void Creat_socket()
    {
        // 1.创建套接字(创建文件细节)
        _sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字(域、套接字类型、协议)参数2基本可以固定tcp/udp
        if (_sockfd < 0)
        {
            cerr << "创建套接字失败" << endl;
            exit(-1);
        }
    }

    void Bind()
    {
        // 2.绑定(网络信息与文件信息相关联)
        struct sockaddr_in local;           //
        local.sin_family = AF_INET;         // 域，用于sockaddr类型接收时的辨别字段
        local.sin_port = htons(_port);      // 端口号 主机转网络(用于发送)
        local.sin_addr.s_addr = INADDR_ANY; // 地址任意

        int n = bind(_sockfd, (sockaddr *)&local, sizeof(local));
        if (n != 0)
        {
            cerr << "套接字绑定失败!!!" << endl;
        }
    }

    void Listen() // 监听，等待客户端进行connect
    {
        if (listen(_sockfd, 5) == -1) // 参数二是全连接队列
        {
            cerr << "listen fails!!!" << endl;
            exit(-1);
        }
    }

    void Run() // 返回一个连接套接字，用于网络数据通信
    {
        while (true)
        {
            struct sockaddr_in local;
            socklen_t len;
            _connect_sockfd = accept(_sockfd, (sockaddr *)&local, &len);
            if (_connect_sockfd < 0)
            {
                cout << "accept error ,continue..." << endl;
                continue;
            }
            cout << "成功接收客户端连接..." << endl;
            Inet_data tmp(_connect_sockfd, local);
            tmp.Inet_info();

            // pattern_1();
            pattern_2();
            close(_connect_sockfd);
        }
    }

    ~Tcp()
    {
    }

private:
    int _sockfd; // socket创建的是监听套接字，用于服务器listen
    uint16_t _port;
    uint16_t _connect_sockfd; // 用于网络通信的连接套接字

    void pattern_1() // 1v1通信
    {
        while (true)
        {
            // 数据读取
            char buffer[1024];
            int n = read(_connect_sockfd, buffer, sizeof(buffer) - 1);
            if (n > 0)
            {
                buffer[n] = 0;
            }
            else if (n == 0) // 对端关闭连接
            {
                cout << "客户端关闭连接，读取完毕..." << endl;
                break;
            }
            else
            {
                cerr << "读取失败..." << endl;
                break;
            }
            cout << "server reading:" << buffer << endl;

            // 数据返回
            write(_connect_sockfd, buffer, n);
        }
    }

    void pattern_2() // 创建(孙子)进程进行通信
    {
        //父进程进行accept客户端，孙子进程进行通信
        
        pid_t id = fork();
        if (id < 0)
        {
            cerr<<"fork失败...."<<endl;
            exit(-1);
        }
        if(id==0)//子进程
        {
            close(_sockfd);
            //子进程再次fork,并退出自己
            //就是因为父进程无法阻塞等待，
            if(fork()>0) exit(0);

            //孙子进程进行与客户端通信（资源由OS管理）
            while (true)
            {
                // 数据读取
                char buffer[1024];
                int n = read(_connect_sockfd, buffer, sizeof(buffer) - 1);
                if (n > 0)
                {
                    buffer[n] = 0;
                }
                else if (n == 0) // 对端关闭连接
                {
                    cout << "客户端关闭连接，读取完毕..." << endl;
                    break;
                }
                else
                {
                    cerr << "读取失败..." << endl;
                    break;
                }
                cout << "server reading:" << buffer << endl;

                // 数据返回
                write(_connect_sockfd, buffer, n);
            }
            close(_connect_sockfd);
            exit(0);

        }
        else//父进程
        {
            close(_connect_sockfd);
            //父进程不用等待子进程，因为子进程已经退出,是孙子进程在执行与客户端通信的功能
            //***父进程也可以采用信号的方式进行管理子进程
            //signal(SIGCHLD,SIG_IGN);写在Run函数的起始位置处，相当于设置信号表中的信号执行方式
            
        }
        
    }
};